#import "mgr_game_mission.h"

#define MAX_ACTIVE_ENEMY_COUNT 1

CMgrGameMission *CMgrGameMission::instance;

void CMgrGameMission::InitInstance(void)
{
	if (NULL == instance)
	{
		instance = new CMgrGameMission;
	}
}

void CMgrGameMission::FreeInstance(void)
{
	if (NULL != instance)
	{
		delete instance;
		instance = NULL;
	}
}

CMgrGameMission *CMgrGameMission::Instance(void)
{
	return instance;
}

void CMgrGameMission::Update(void)
{
	int i;
	float _GroupDelayTime;
	std::vector<SMissionEnemy> *_Group;

	switch (mission_state)
	{
	case MISSION_STATE_INVALID: break;
	case MISSION_STATE_SCENE_PREVIEW: break;
	case MISSION_STATE_SCENE_PERVIEW_OVER: break;
	case MISSION_STATE_LAYER_OBJECT_READY: break;
	case MISSION_STATE_TUTORAIL_WAIT: break;
	case MISSION_STATE_PLAY:
		if (flag_group_delay_tick)
		{
			_GroupDelayTime = group_delay_tick_count * (1.0f / 60.0f);
			_Group = &enemy_table.find(group_index)->second;
			for (i = 0; i < _Group->size(); i++)
			{
				if (((*_Group)[i].born_delay <= _GroupDelayTime) && !(*_Group)[i].flag_is_loaded)
				{
					LoadEnemy(&(*_Group)[i]);
				}
			}
			group_delay_tick_count++;
		}

		/*create heart by time
		*/
		create_heart_tick++;
		if (create_heart_tick > 600)
		{
			create_heart_tick = 0;
			int _AreaIndex = rand() % 9;
			sprite_game_heart *_Heart = [[sprite_game_heart alloc] initSpriteGameHeart:5];
			[g_LayerGameObject AddHeart:_Heart];
			_Heart.positionInPixels = g_CfgGameScrrenArea[_AreaIndex].center;
		}
		break;
	case MISSION_STATE_ENEMY_ALL_DIE:
		EventEnemyAllKilledSuccess();
		mission_state = MISSION_STATE_WIN_ALL_ENEMY_KILL;
		break;
	case MISSION_STATE_WAIT_BIRDGE_SUCCESS_ANI: break;
	case MISSION_STATE_WIN_ALL_ENEMY_KILL: break;
	case MISSION_STATE_WIN: break;
	case MISSION_STATE_FAIL: break;
	case MISSION_STATE_TIME_UP: break;
	default:;
	}
}

void CMgrGameMission::SetMissionState(int State)
{
	switch (State)
	{
	case MISSION_STATE_SCENE_PREVIEW:
		mission_state = MISSION_STATE_SCENE_PREVIEW;
		[g_LayerGameObject runAction:[CCHide action]];
		[g_LayerGameBackground ActionMissionPreview];
		break;
	case MISSION_STATE_SCENE_PERVIEW_OVER:
		mission_state = MISSION_STATE_SCENE_PERVIEW_OVER;
		[g_LayerGameObject ActionPreview];
		break;
	case MISSION_STATE_LAYER_OBJECT_READY:
		if (1 == mission_id)
		{
			mission_state = MISSION_STATE_TUTORAIL_WAIT;
			[g_LayerGameObject ActionToturialMain];
		}
		else
		{
			mission_state = MISSION_STATE_PLAY;
			EventMissionStart();
		}
		break;
	case MISSION_STATE_PLAY: break;
	default:;
	}
}

void CMgrGameMission::ToturialCreateHeart(void)
{
	sprite_game_heart *_Heart;

	_Heart = [[sprite_game_heart alloc] initSpriteGameHeart:5];
	[g_LayerGameObject AddHeart:_Heart];
	_Heart.positionInPixels = g_CfgGameScrrenArea[7].center;
	[_Heart ActionToturial];
	[g_LayerGameObject ActionToturialHeartAppear];
}

void CMgrGameMission::ToturialCreateEnemy(void)
{
	sprite_game_enemy *_Enemy;
	SMissionEnemy _EnemyInfo;

	_EnemyInfo.enemy_type = 0;
	_EnemyInfo.ai_type = 2;
	_EnemyInfo.born_area.point = g_CfgGameScrrenArea[14].center;
	_EnemyInfo.drop_heart_point = 0;
	_Enemy = [[sprite_game_enemy alloc] initSpriteGameEnemy:&_EnemyInfo];
	[g_LayerGameObject AddEnemy:_Enemy];
	_Enemy.positionInPixels = g_CfgGameScrrenArea[14].center;
	[_Enemy ActionToturial];
}

void CMgrGameMission::ToturialEnemyMoveOver(void)
{
	[g_LayerGameObject ActionToturialEnemy];
}

void CMgrGameMission::ToturialOver(void)
{
	mission_state = MISSION_STATE_PLAY;
	CMgrGameMission::EventMissionStart();
}

void CMgrGameMission::EventMissionStart(void)
{
	int i;
	std::map<int, std::vector<SMissionEnemy> >::iterator _MapIter;

	/*clear enemy table loaded flag
	*/
	_MapIter = enemy_table.begin();
	for (; _MapIter != enemy_table.end(); _MapIter++)
	{
		for (i = 0; i < _MapIter->second.size(); i++)
		{
			_MapIter->second[i].flag_is_loaded = false;
		}
	}

	/*load first group
	*/
	flag_group_delay_tick = true;
	group_index = 0;
	LoadGroup();

	/*flag
	*/
	flag_enemy_disappear = false;
	create_heart_tick = 0;

	[g_LayerGameObject MissionStart];
	[g_SpriteGameBridge MissionStart];
	[g_SpriteGameTimeBar MissionStart];

	/*mission record
	*/
	mission_recrod.flag_star_heart = false;
	mission_recrod.flag_star_enemy = false;
	mission_recrod.flag_star_special = false;
}

void CMgrGameMission::EventEnemyKilled(sprite_game_enemy *Enemy)
{
	int i;
	std::vector<SMissionEnemy> *_Group;
	sprite_game_heart *_Heart;

	if (MISSION_STATE_TUTORAIL_WAIT == mission_state)
	{
		[g_LayerGameObject ActionToturialOver];
	}
	else
	{
		/*check and create heart
		*/
		_Group = &enemy_table.find(group_index)->second;
		for (i = 0; i < _Group->size(); i++)
		{
			if ((*_Group)[i].object == Enemy)
			{
				if ((*_Group)[i].drop_heart_point > 0)
				{
					_Heart = [[sprite_game_heart alloc] initSpriteGameHeart:(*_Group)[i].drop_heart_point];
					[g_LayerGameObject AddHeart:_Heart];
					_Heart.positionInPixels = (*_Group)[i].object.positionInPixels;
				}
				(*_Group)[i].object = nil;
				break;
			}
		}

		/*check and load group
		*/
		group_enemy_count--;
		if (0 == group_enemy_count)
		{
			group_index++;
			if (!LoadGroup())
			{
				mission_state = MISSION_STATE_ENEMY_ALL_DIE;
			}
		}
	}
}

void CMgrGameMission::EventEnemyDisappear(sprite_game_enemy *Enemy)
{
	int i;
	std::vector<SMissionEnemy> *_Group;

	/*clear handle
	*/
	_Group = &enemy_table.find(group_index)->second;
	for (i = 0; i < _Group->size(); i++)
	{
		if ((*_Group)[i].object == Enemy)
		{
			(*_Group)[i].object = nil;
			break;
		}
	}

	/*check and load group
	*/
	group_enemy_count--;
	if (0 == group_enemy_count)
	{
		group_index++;
		if (!LoadGroup())
		{
			mission_state = MISSION_STATE_ENEMY_ALL_DIE;
		}
	}

	/*flag
	*/
	flag_enemy_disappear = true;
}

void CMgrGameMission::EventEnemyAttackSuccess(sprite_game_bomb *Bomb)
{
	[g_SpriteGameBridge DecPoint:Bomb.attackPoint];
}

void CMgrGameMission::EventHeartGet(sprite_game_heart *Heart)
{
	if (MISSION_STATE_TUTORAIL_WAIT == mission_state)
	{
		[g_LayerGameObject ActionToturialHeartGet];
	}
	else if (Heart.flagDark)
	{
		[g_SpriteGameBridge DecPoint:Heart.heartPoint];
	}
	else
	{
		[g_SpriteGameBridge AddPoint:Heart.heartPoint];
	}
}

void CMgrGameMission::EventBridgeSuccess(void)
{
	switch (mission_type)
	{
	case MISSION_TYPE_NORMAL:
		/*change state
		*/
		mission_state = MISSION_STATE_WAIT_BIRDGE_SUCCESS_ANI;

		/*mission over
		*/
		MissionOver();
		[g_LayerGameObject MissionWin];

		/*bridge ani
		*/
		[g_SpriteGameBridge ActionSuccess];

		/*record
		*/
		mission_recrod.flag_star_heart = true;
		break;
	case MISSION_TYPE_BOSS: break;
	default:;
	}
}

void CMgrGameMission::EventBridgeSuccessAniOver(void)
{
	/*record
	*/
	MissionWinRecordControl();

	/*menu
	*/
	g_LayerGameMenu = [[layer_game_menu alloc] initLayerGameMenu:GAME_MENU_STATE_WIN];
	[g_SceneGame addChild:g_LayerGameMenu];
	[g_LayerGameMenu release];

	/*get item
	*/
	[g_LayerGameMenu CreateMenuGetItem];
}

void CMgrGameMission::EventBridgeFailed(void)
{
	/*change state
	*/
	mission_state = MISSION_STATE_FAIL;

	MissionOver();
	[g_LayerGameObject MissionLose];
	g_LayerGameMenu = [[layer_game_menu alloc] initLayerGameMenu:GAME_MENU_STATE_LOSE];
	[g_SceneGame addChild:g_LayerGameMenu];
	[g_LayerGameMenu release];
}

void CMgrGameMission::EventEnemyAllKilledSuccess(void)
{
	/*mission win
	*/
	MissionOver();
	[g_LayerGameObject MissionWin];

	/*record
	*/
	switch (mission_type)
	{
	case MISSION_TYPE_NORMAL:
		if (!flag_enemy_disappear)
		{
			mission_recrod.flag_star_enemy = true;
		}
		break;
	case MISSION_TYPE_BOSS:
		/*kill boss
		*/
		mission_recrod.flag_star_kill_boss = true;

		/*perfect
		*/
		if (100 == g_SpriteGameBridge.point)
		{
			mission_recrod.flag_star_perfect = true;
		}
		break;
	}
	MissionWinRecordControl();

	/*menu
	*/
	g_LayerGameMenu = [[layer_game_menu alloc] initLayerGameMenu:GAME_MENU_STATE_WIN];
	[g_SceneGame addChild:g_LayerGameMenu];
	[g_LayerGameMenu release];

	/*get item
	*/
	[g_LayerGameMenu CreateMenuGetItem];
}

void CMgrGameMission::LoadMission(int MissionID)
{
	char _Buffer[256];
	FILE *_File;
	mxml_node_t *_NodeXml, *_NodeBouy;

	memset(_Buffer, 0, sizeof _Buffer);
	[[CCFileUtils fullPathFromRelativePath:[NSString stringWithFormat:@"file_mission_%d.xml", MissionID]] getCString:_Buffer maxLength:sizeof _Buffer encoding:NSASCIIStringEncoding];
	_File = fopen(_Buffer, "r");
	if (NULL != _File)
	{
		_NodeXml = mxmlLoadFile(NULL, _File, MXML_TEXT_CALLBACK);
		_NodeBouy = mxmlGetFirstChild(_NodeXml);
		for (; NULL != _NodeBouy; _NodeBouy = mxmlWalkNext(_NodeBouy, _NodeXml, MXML_NO_DESCEND))
		{
			if (tmxmlIsElement(_NodeBouy, "mission_id"))
			{
				mission_id = tmxmlElementReadChildInt(_NodeBouy);
			}
			else if (tmxmlIsElement(_NodeBouy, "mission_type"))
			{
				mission_type = tmxmlElementReadChildInt(_NodeBouy);
			}
			else if (tmxmlIsElement(_NodeBouy, "next_mission_id"))
			{
				next_mission_id = tmxmlElementReadChildInt(_NodeBouy);
			}
			else if (tmxmlIsElement(_NodeBouy, "background_type"))
			{
				background_type = tmxmlElementReadChildInt(_NodeBouy);
			}
			else if (tmxmlIsElement(_NodeBouy, "start_bridge_point"))
			{
				start_bridge_point = tmxmlElementReadChildInt(_NodeBouy);
			}
			else if (tmxmlIsElement(_NodeBouy, "item_drop_max"))
			{
				mission_piece_drop_max_count = tmxmlElementReadChildInt(_NodeBouy);
			}
			else if (tmxmlIsElement(_NodeBouy, "item_drop_probability"))
			{
				tmxmlReadIntArray(_NodeBouy, mission_piece_drop_probability, "data");
			}
			else if (tmxmlIsElement(_NodeBouy, "enemy_table"))
			{
				LoadEnemyTable(_NodeBouy);
			}
		}
	}
}

void CMgrGameMission::MissionRestart(void)
{
	mission_state = MISSION_STATE_PLAY;
	[g_LayerGameObject MissionStart];
	[g_LayerGameMenu MissionStart];
	[g_SpriteGameBridge MissionStart];
	[g_SpriteGameTimeBar MissionStart];
	EventMissionStart();
}

void CMgrGameMission::MissionOver(void)
{
	flag_group_delay_tick = false;
	[g_LayerGameObject MissonOver];
}

void CMgrGameMission::MissionTimeUp(void)
{
	/*change state
	*/
	mission_state = MISSION_STATE_TIME_UP;

	[g_LayerGameObject MissionLose];
	[g_LayerGameObject MissonOver];
	g_LayerGameMenu = [[layer_game_menu alloc] initLayerGameMenu:GAME_MENU_STATE_TIME_UP];
	[g_SceneGame addChild:g_LayerGameMenu];
	[g_LayerGameMenu release];
}

void CMgrGameMission::MissionNext(void)
{
	/*flag
	*/
	g_ChapterNextMissionID = next_mission_id;

	[g_SceneGame SceneChangeToComic];
}

void CMgrGameMission::MissionQuit(void)
{
	MissionOver();
}

void CMgrGameMission::LoadResource(void)
{
	bool flag0To4Enemy;
	std::list<int>::iterator _Iter;

	flag0To4Enemy = false;
	_Iter = enemy_type_list.begin();
	for (; _Iter != enemy_type_list.end(); _Iter++)
	{
		if (*_Iter < 5)
		{
			if (!flag0To4Enemy)
			{
				reLoadResource(&g_CfgGameEnemyResourceTable.find(0)->second);
				flag0To4Enemy = true;
			}
		}
		else
		{
			reLoadResource(&g_CfgGameEnemyResourceTable.find(*_Iter)->second);
		}
	}
}

void CMgrGameMission::FreeResource(void)
{
	bool flag0To4Enemy;
	std::list<int>::iterator _Iter;

	flag0To4Enemy = false;
	_Iter = enemy_type_list.begin();
	for (; _Iter != enemy_type_list.end(); _Iter++)
	{
		if (*_Iter < 5)
		{
			if (!flag0To4Enemy)
			{
				reFreeResource(&g_CfgGameEnemyResourceTable.find(0)->second);
				flag0To4Enemy = true;
			}
		}
		else
		{
			reFreeResource(&g_CfgGameEnemyResourceTable.find(*_Iter)->second);
		}
	}
}

void CMgrGameMission::LoadEnemyTable(mxml_node_t *Element)
{
	int _GroupIndex;
	mxml_node_t *_Bouy, *_GroupBouy, *_EnemyBouy, *_EnemyPathElement;
	std::vector<SMissionEnemy> _Group;
	SMissionEnemy _Enemy;
	SMissionEnemyPathElement _PathElement;

	_GroupIndex = 0;
	_Bouy = mxmlGetFirstChild(Element);
	for (; NULL != _Bouy; _Bouy = mxmlWalkNext(_Bouy, Element, MXML_NO_DESCEND))
	{
		if (tmxmlIsElement(_Bouy, "group"))
		{
			_Group.clear();
			_GroupBouy = mxmlGetFirstChild(_Bouy);
			for (; NULL != _GroupBouy; _GroupBouy = mxmlWalkNext(_GroupBouy, _Bouy, MXML_NO_DESCEND))
			{
				if (tmxmlIsElement(_GroupBouy, "enemy"))
				{
					/*clear enemy
					*/
					_Enemy.flag_is_loaded = false;
					_Enemy.enemy_type = 0;
					_Enemy.ai_type = 0;
					_Enemy.born_delay = 0.0f;
					memset(&_Enemy.born_area, 0, sizeof(SMissionEnemyPathElement));
					_Enemy.move_path_table.clear();
					_Enemy.move_speed = 0.0f;
					_Enemy.stand_time = 0.0f;
					_Enemy.drop_heart_point = 0;
					_Enemy.object = nil;

					/*load data
					*/
					_EnemyBouy = mxmlGetFirstChild(_GroupBouy);
					for (; NULL != _EnemyBouy; _EnemyBouy = mxmlWalkNext(_EnemyBouy, _GroupBouy, MXML_NO_DESCEND))
					{
						if (tmxmlIsElement(_EnemyBouy, "enemy_type"))
						{
							_Enemy.enemy_type = tmxmlElementReadChildInt(_EnemyBouy);
						}
						else if (tmxmlIsElement(_EnemyBouy, "ai_type"))
						{
							_Enemy.ai_type = tmxmlElementReadChildInt(_EnemyBouy);
						}
						else if (tmxmlIsElement(_EnemyBouy, "born_delay"))
						{
							_Enemy.born_delay = tmxmlElementReadChildFloat(_EnemyBouy);
						}
						else if (tmxmlIsElement(_EnemyBouy, "born_area"))
						{
							LoadEnemyMovePath(_EnemyBouy, &_Enemy.born_area);
						}
						else if (tmxmlIsElement(_EnemyBouy, "move_path"))
						{
							_EnemyPathElement = mxmlGetFirstChild(_EnemyBouy);
							for (; NULL != _EnemyPathElement; _EnemyPathElement = mxmlWalkNext(_EnemyPathElement, _EnemyBouy, MXML_NO_DESCEND))
							{
								if (tmxmlIsElement(_EnemyPathElement, "data"))
								{
									/*clear path element
									*/
									memset(&_PathElement, 0, sizeof(SMissionEnemyPathElement));

									/*load data
									*/
									LoadEnemyMovePath(_EnemyPathElement, &_PathElement);
									_Enemy.move_path_table.push_back(_PathElement);
								}
							}
						}
						else if (tmxmlIsElement(_EnemyBouy, "move_speed"))
						{
							_Enemy.move_speed = tmxmlElementReadChildFloat(_EnemyBouy);
						}
						else if (tmxmlIsElement(_EnemyBouy, "move_speed"))
						{
							_Enemy.move_speed_variance = tmxmlElementReadChildFloat(_EnemyBouy);
						}
						else if (tmxmlIsElement(_EnemyBouy, "stand_time"))
						{
							_Enemy.stand_time = tmxmlElementReadChildFloat(_EnemyBouy);
						}
						else if (tmxmlIsElement(_EnemyBouy, "drop_heart_point"))
						{
							_Enemy.drop_heart_point = tmxmlElementReadChildInt(_EnemyBouy);
						}
					}
					_Group.push_back(_Enemy);

					/*check and add to enemy type list
					*/
					if (enemy_type_list.end() == std::find(enemy_type_list.begin(), enemy_type_list.end(), _Enemy.enemy_type))
					{
						enemy_type_list.push_back(_Enemy.enemy_type);
					}
				}
			}
			enemy_table.insert(std::pair<int, std::vector<SMissionEnemy> >(_GroupIndex, _Group));
			_GroupIndex++;
		}
	}
}

void CMgrGameMission::LoadEnemyMovePath(mxml_node_t *Element, SMissionEnemyPathElement *Object)
{
	mxml_node_t *_EnemyPathElementBouy;

	_EnemyPathElementBouy = mxmlGetFirstChild(Element);
	for (; NULL != _EnemyPathElementBouy; _EnemyPathElementBouy = mxmlWalkNext(_EnemyPathElementBouy, Element, MXML_NO_DESCEND))
	{
		if (tmxmlIsElement(_EnemyPathElementBouy, "path_type"))
		{
			Object->path_type = tmxmlElementReadChildInt(_EnemyPathElementBouy);
		}
		else if (tmxmlIsElement(_EnemyPathElementBouy, "area_index"))
		{
			Object->area_index = tmxmlElementReadChildInt(_EnemyPathElementBouy);
		}
		else if (tmxmlIsElement(_EnemyPathElementBouy, "point"))
		{
			uiLoadPointFromXML(_EnemyPathElementBouy, &Object->point);
		}
	}
}

bool CMgrGameMission::LoadGroup(void)
{
	std::map<int, std::vector<SMissionEnemy> >::iterator _MapIter;
	std::vector<SMissionEnemy> *_Group;

	group_delay_tick_count = 0;
	_MapIter = enemy_table.find(group_index);
	if (_MapIter != enemy_table.end())
	{
		_Group = &_MapIter->second;
		group_enemy_count = _Group->size();
		return true;
	}
	else
	{
		return false;
	}
}

void CMgrGameMission::LoadEnemy(SMissionEnemy *Data)
{
	Data->flag_is_loaded = true;
	Data->object = [[sprite_game_enemy alloc] initSpriteGameEnemy:Data];
	[g_LayerGameObject AddEnemy:Data->object];
	[Data->object AiCreate];
}

CMgrGameMission::CMgrGameMission(void)
{
	/*mission state
	*/
	mission_state = MISSION_STATE_INVALID;

	/*mission data
	*/
	mission_id = -1;
	mission_type = -1;
	background_type = -1;
	start_bridge_point = -1;
	memset(music_start, 0, sizeof music_start);
	memset(music_battle, 0, sizeof music_battle);

	/*flag
	*/
	group_index = 0;
	group_enemy_count = 0;
	flag_group_delay_tick = false;
	group_delay_tick_count = 0;
	flag_enemy_disappear = false;
}

CMgrGameMission::~CMgrGameMission(void)
{}

void CMgrGameMission::MissionWinRecordControl(void)
{
	/*mission lock
	*/
	switch (mission_type)
	{
	case MISSION_TYPE_NORMAL:
		if ((-1 != next_mission_id) && (true == g_RecordMissionLock[next_mission_id]))
		{
			g_RecordMissionLock[next_mission_id] = false;
		}
		break;
	case MISSION_TYPE_BOSS: break;
	default:;
	}

	/*mission record
	*/
	switch (mission_type)
	{
	case MISSION_TYPE_NORMAL:
		if (mission_recrod.flag_star_heart && !g_RecordMission[mission_id].flag_star_heart)
		{
			g_RecordMission[mission_id].flag_star_heart = true;
		}
		if (mission_recrod.flag_star_enemy && !g_RecordMission[mission_id].flag_star_enemy)
		{
			g_RecordMission[mission_id].flag_star_enemy = true;
		}
		if (mission_recrod.flag_star_special && !g_RecordMission[mission_id].flag_star_special)
		{
			g_RecordMission[mission_id].flag_star_special = true;
		}
		break;
	case MISSION_TYPE_BOSS:
		if (mission_recrod.flag_star_kill_boss && !g_RecordMission[mission_id].flag_star_kill_boss)
		{
			g_RecordMission[mission_id].flag_star_kill_boss = true;
		}
		if (mission_recrod.flag_star_perfect && !g_RecordMission[mission_id].flag_star_perfect)
		{
			g_RecordMission[mission_id].flag_star_perfect = true;
		}
		if (mission_recrod.flag_star_special && !g_RecordMission[mission_id].flag_star_special)
		{
			g_RecordMission[mission_id].flag_star_special = true;
		}
		break;
	default:;
	}

	/*save record
	*/
	RecordSave();
}